package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.query.NoteQuery;
import com.zenithmind.note.pojo.vo.NoteVO;
import com.zenithmind.note.pojo.vo.NoteTagVO;
import com.zenithmind.note.service.NoteQueryService;
import com.zenithmind.note.service.NoteService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 笔记查询服务实现类
 * 遵循单一职责原则：专门负责笔记的查询操作
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteQueryServiceImpl implements NoteQueryService {

    private final NoteMapper noteMapper;
    private final NoteService noteService;

    @Override
    public Note getNoteById(String id) {
        try {
            if (!StringUtils.hasText(id)) {
                return null;
            }
            return noteMapper.selectById(id);
        } catch (Exception e) {
            log.error("根据ID获取笔记失败：id={}", id, e);
            return null;
        }
    }

    @Override
    public NoteVO getNoteDetail(String id, String userId) {
        try {
            Note note = getNoteById(id);
            if (note == null) {
                return null;
            }
            return convertToVO(note);
        } catch (Exception e) {
            log.error("获取笔记详情失败：id={}, userId={}", id, userId, e);
            return null;
        }
    }

    @Override
    public PageResult<NoteVO> queryNotePage(NoteQuery query) {
        try {
            Page<Note> page = new Page<>(query.getCurrent(), query.getSize());
            LambdaQueryWrapper<Note> wrapper = buildQueryWrapper(query);

            IPage<Note> notePage = noteMapper.selectPage(page, wrapper);

            List<NoteVO> noteVOList = notePage.getRecords().stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());

            return new PageResult<>(noteVOList, notePage.getTotal(), notePage.getCurrent(), notePage.getSize());
        } catch (Exception e) {
            log.error("分页查询笔记失败：query={}", query, e);
            return new PageResult<>(List.<NoteVO>of(), 0L, query.getCurrent().longValue(), query.getSize().longValue());
        }
    }

    @Override
    public PageResult<NoteVO> getUserNotes(String userId, long current, long size) {
        try {
            Page<Note> page = new Page<>(current, size);
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StringUtils.hasText(userId), Note::getUserId, userId)
                   .eq(Note::getStatus, 1) // 已发布
                   .orderByDesc(Note::getCreateTime);

            IPage<Note> notePage = noteMapper.selectPage(page, wrapper);

            List<NoteVO> noteVOList = notePage.getRecords().stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());

            return new PageResult<>(noteVOList, notePage.getTotal(), notePage.getCurrent(), notePage.getSize());
        } catch (Exception e) {
            log.error("获取用户笔记失败：userId={}", userId, e);
            return new PageResult<>(List.<NoteVO>of(), 0L, current, size);
        }
    }

    @Override
    public List<NoteTagVO> getNoteTagList(String noteId) {
        try {
            return noteService.getNoteTagList(noteId);
        } catch (Exception e) {
            log.error("获取笔记标签列表失败：noteId={}", noteId, e);
            return List.<NoteTagVO>of();
        }
    }

    @Override
    public boolean hasAccessPermission(String noteId, String userId) {
        try {
            Note note = getNoteById(noteId);
            if (note == null) {
                return false;
            }

            // 如果是公开笔记，所有人都可以访问
            if (note.getStatus() == 1) {
                return true;
            }

            // 如果是私有笔记，只有作者可以访问
            return StringUtils.hasText(userId) && userId.equals(note.getUserId());
        } catch (Exception e) {
            log.error("检查笔记访问权限失败：noteId={}, userId={}", noteId, userId, e);
            return false;
        }
    }

    @Override
    public List<NoteVO> getHotNotes(int limit) {
        try {
            // 查询热门笔记：按点赞数和浏览数排序
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Note::getStatus, 1) // 已发布
                   .orderByDesc(Note::getLikeCount)
                   .orderByDesc(Note::getViewCount)
                   .orderByDesc(Note::getCreateTime)
                   .last("LIMIT " + limit);
            
            List<Note> notes = noteMapper.selectList(wrapper);
            return notes.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取热门笔记失败", e);
            return List.<NoteVO>of();
        }
    }

    @Override
    public List<NoteVO> getLatestNotes(int limit) {
        try {
            // 查询最新笔记：按创建时间排序
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Note::getStatus, 1) // 已发布
                   .orderByDesc(Note::getCreateTime)
                   .last("LIMIT " + limit);
            
            List<Note> notes = noteMapper.selectList(wrapper);
            return notes.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取最新笔记失败", e);
            return List.<NoteVO>of();
        }
    }

    @Override
    public PageResult<NoteVO> searchNotes(String keyword, long current, long size) {
        try {
            Page<Note> page = new Page<>(current, size);
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            
            if (StringUtils.hasText(keyword)) {
                wrapper.and(w -> w.like(Note::getTitle, keyword)
                                 .or()
                                 .like(Note::getContent, keyword)
                                 .or()
                                 .like(Note::getTags, keyword));
            }
            
            wrapper.eq(Note::getStatus, 1) // 已发布
                   .orderByDesc(Note::getCreateTime);
            
            IPage<Note> notePage = noteMapper.selectPage(page, wrapper);
            
            List<NoteVO> noteVOList = notePage.getRecords().stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());
            
            return new PageResult<>(noteVOList, notePage.getTotal(), notePage.getCurrent(), notePage.getSize());
        } catch (Exception e) {
            log.error("搜索笔记失败：keyword={}", keyword, e);
            return new PageResult<>(List.<NoteVO>of(), 0L, current, size);
        }
    }

    @Override
    public List<NoteVO> getRelatedNotes(String noteId, int limit) {
        try {
            // 获取当前笔记信息
            Note currentNote = noteMapper.selectById(noteId);
            if (currentNote == null) {
                return List.<NoteVO>of();
            }
            
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Note::getStatus, 1) // 已发布
                   .ne(Note::getId, noteId); // 排除当前笔记
            
            // 如果有分类，优先推荐同分类的笔记
            if (StringUtils.hasText(currentNote.getCategoryId())) {
                wrapper.eq(Note::getCategoryId, currentNote.getCategoryId());
            }
            
            // 如果有标签，推荐相同标签的笔记
            if (StringUtils.hasText(currentNote.getTags())) {
                String[] tags = currentNote.getTags().split(",");
                for (String tag : tags) {
                    wrapper.or().like(Note::getTags, tag.trim());
                }
            }
            
            wrapper.orderByDesc(Note::getLikeCount)
                   .orderByDesc(Note::getViewCount)
                   .orderByDesc(Note::getCreateTime)
                   .last("LIMIT " + limit);
            
            List<Note> notes = noteMapper.selectList(wrapper);
            return notes.stream()
                    .map(this::convertToVO)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取相关笔记失败：noteId={}", noteId, e);
            return List.<NoteVO>of();
        }
    }

    @Override
    public List<Map<String, Object>> getTagsWithCount() {
        try {
            // 查询所有已发布笔记的标签
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(Note::getTags)
                   .eq(Note::getStatus, 1)
                   .isNotNull(Note::getTags)
                   .ne(Note::getTags, "");
            
            List<Note> notes = noteMapper.selectList(wrapper);
            
            // 统计标签使用次数
            Map<String, Integer> tagCountMap = new HashMap<>();
            for (Note note : notes) {
                String tags = note.getTags();
                if (StringUtils.hasText(tags)) {
                    String[] tagArray = tags.split(",");
                    for (String tag : tagArray) {
                        tag = tag.trim();
                        if (StringUtils.hasText(tag)) {
                            tagCountMap.put(tag, tagCountMap.getOrDefault(tag, 0) + 1);
                        }
                    }
                }
            }
            
            // 转换为前端需要的格式并按使用次数排序
            return tagCountMap.entrySet().stream()
                    .map(entry -> {
                        Map<String, Object> map = new HashMap<>();
                        map.put("name", entry.getKey());
                        map.put("count", entry.getValue());
                        return map;
                    })
                    .sorted((a, b) -> Integer.compare((Integer) b.get("count"), (Integer) a.get("count")))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取标签统计失败", e);
            return List.<Map<String, Object>>of();
        }
    }

    @Override
    public boolean noteExists(String id) {
        try {
            if (!StringUtils.hasText(id)) {
                return false;
            }
            
            LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Note::getId, id)
                   .eq(Note::getStatus, 1); // 已发布
            
            return noteMapper.selectCount(wrapper) > 0;
        } catch (Exception e) {
            log.error("检查笔记是否存在失败：id={}", id, e);
            return false;
        }
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<Note> buildQueryWrapper(NoteQuery query) {
        LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();

        // 基础条件
        if (query.getStatus() != null) {
            wrapper.eq(Note::getStatus, query.getStatus());
        } else {
            wrapper.eq(Note::getStatus, 1); // 默认只查询已发布的笔记
        }

        // 动态条件
        if (StringUtils.hasText(query.getTitle())) {
            wrapper.like(Note::getTitle, query.getTitle());
        }

        if (StringUtils.hasText(query.getCategoryId())) {
            wrapper.eq(Note::getCategoryId, query.getCategoryId());
        }

        if (query.getUserId() != null) {
            wrapper.eq(Note::getUserId, query.getUserId());
        }

        if (query.getCourseId() != null) {
            wrapper.eq(Note::getCourseId, query.getCourseId());
        }

        if (StringUtils.hasText(query.getTags())) {
            wrapper.like(Note::getTags, query.getTags());
        }

        if (query.getNoteIds() != null && !query.getNoteIds().isEmpty()) {
            wrapper.in(Note::getId, query.getNoteIds());
        }

        // 排序
        wrapper.orderByDesc(Note::getCreateTime);

        return wrapper;
    }

    /**
     * 转换为VO对象
     */
    private NoteVO convertToVO(Note note) {
        NoteVO vo = new NoteVO();
        BeanUtils.copyProperties(note, vo);

        // 设置标签列表
        if (StringUtils.hasText(note.getTags())) {
            vo.setTagList(noteService.getNoteTagList(note.getId()));
        }

        return vo;
    }
}
